package com.cuixichang.minimalism.support;

import com.cuixichang.minimalism.basal.cnstants.HttpHeader;
import com.cuixichang.minimalism.basal.enums.RouterRelationTypeEnum;
import com.cuixichang.minimalism.basal.exceptions.ServiceException;
import com.cuixichang.minimalism.core.security.design.RuleDefinitionDesign;
import com.cuixichang.minimalism.core.security.enums.RouterRelationTypePrefixEnum;
import com.cuixichang.minimalism.service.IPermissionService;
import com.cuixichang.minimalism.service.IRoleService;
import com.cuixichang.minimalism.service.IRouterRelationService;
import com.cuixichang.minimalism.service.IRouterService;
import com.cuixichang.minimalism.transfer.dto.IPermissionDTO;
import com.cuixichang.minimalism.transfer.dto.IRoleDTO;
import com.cuixichang.minimalism.transfer.dto.IRouterDTO;
import com.cuixichang.minimalism.transfer.dto.IRouterRelationDTO;
import com.cuixichang.minimalism.transfer.po.IPermission;
import com.cuixichang.minimalism.transfer.po.IRole;
import com.cuixichang.minimalism.transfer.po.IRouter;
import com.cuixichang.minimalism.transfer.po.IRouterRelation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Component("prevalidationCollection")
public class CustomPrevalidationCollection implements RuleDefinitionDesign {
    @Autowired
    private IRouterService routerService;
    @Autowired
    private IRouterRelationService routerRelationService;
    @Autowired
    private IRoleService roleService;
    @Autowired
    private IPermissionService permissionService;
    @Override
    public List<ConfigAttribute> configAttributes(HttpServletRequest request, String mate) {
        String systemCode = request.getHeader(HttpHeader.SYSTEM_SOURCE_CODE);
        IRouterDTO iRouter = routerService.selectOne(IRouterDTO.builder().createSystemCode(systemCode).routerUrl(mate)
                .requestType(request.getMethod()).build());
        List<ConfigAttribute> configAttributes = new ArrayList<>();
        if(Objects.nonNull(iRouter)){
            RouterRelationTypeEnum[] routerRelationTypeEnums = RouterRelationTypeEnum.values();
            for (RouterRelationTypeEnum routerRelationTypeEnum : routerRelationTypeEnums) {
                RouterRelationTypePrefixEnum enumByRouterRelationType = RouterRelationTypePrefixEnum
                        .getEnumByRouterRelationType(routerRelationTypeEnum);
                if(Objects.nonNull(enumByRouterRelationType)){
                    List<IRouterRelationDTO> iRouterRelations = routerRelationService.selectList(IRouterRelationDTO.builder().routerId(iRouter.getId())
                            .roleRelation(RouterRelationTypeEnum.RoleType.equals(routerRelationTypeEnum)).isEnable(true).build());
                    String prefix = enumByRouterRelationType.getPrefix();
                    if(!CollectionUtils.isEmpty(iRouterRelations)){
                        List<Long> relationIds = iRouterRelations.stream().map(IR -> IR.getRelationId()).collect(Collectors.toList());
                        if(RouterRelationTypeEnum.RoleType.equals(routerRelationTypeEnum)){
                            List<IRoleDTO> iRoles = roleService.selectByIds(relationIds);
                            if(!CollectionUtils.isEmpty(iRoles)){
                                List<ConfigAttribute> roleCodes = iRoles.stream().filter(IRoleDTO::getIsEnable)
                                        .map(IRoleDTO::getRoleCode).map(prefix::concat).map(SecurityConfig::new).collect(Collectors.toList());
                                configAttributes.addAll(roleCodes);
                            }
                        }else if (RouterRelationTypeEnum.PermissionType.equals(routerRelationTypeEnum)){
                            List<IPermissionDTO> iPermissions = permissionService.selectByIds(relationIds);
                            if(!CollectionUtils.isEmpty(iPermissions)){
                                List<ConfigAttribute> permissionCodes = iPermissions.stream().filter(IPermissionDTO::getIsEnable)
                                        .map(IPermissionDTO::getPermissionCode).map(prefix::concat).map(SecurityConfig::new).collect(Collectors.toList());
                                configAttributes.addAll(permissionCodes);
                            }
                        }else {
                            throw new ServiceException("新增路由关系信息未知,请维护相关逻辑应用",null);
                        }
                    }
                }
            }
        }
        return configAttributes;
    }
}
